/*
 * random_generator.hpp
 *
 *  Created on: Mar 19, 2009
 *      Author: Lev
 */

#ifndef RANDOM_GENERATOR_HPP_
#define RANDOM_GENERATOR_HPP_

#include <utility>

// generates uniform random numbers in the given/default range
class RandomGenerator {
	typedef int (*RandFunc)( void );
	typedef void (*SeedFunc)( unsigned int );
private:
	RandFunc _randFunc;
	SeedFunc _seedFunc;
	int _maxRandNumber;
	std::pair<int, int> _intRange;
	std::pair<double, double> _doubleRange;
	void init( unsigned int seed ) const;
	int nextRand() const;
public:
	RandomGenerator();
	RandomGenerator( const std::pair<int, int> &range );
	RandomGenerator( const std::pair<double, double> &range );
	RandomGenerator( const std::pair<int, int> &iRange, const std::pair<double, double> &dRange );
	RandomGenerator( const RandomGenerator &that );
	RandomGenerator& operator= ( const RandomGenerator &that );
	void setAlgorithm( RandFunc randFunc, SeedFunc seedFunc, unsigned int maxRandNumber );
	inline const std::pair<int, int>& getIntRange() const { return _intRange; }
	inline const std::pair<double, double>& getDoubleRange() const { return _doubleRange; }
	inline int getMaxRandomNumber() const { return _maxRandNumber; }
	int nextInt() const;
	double nextDouble() const;
};

// generates normal random numbers with the given/default mean/sigma
class NormalRandomNumber {
private:
	RandomGenerator _random;
	int _nextIndex;
	double _mean;
	double _sigma;
	std::pair<double, double> _normalPair;
	void generateNextPair();
public:
	NormalRandomNumber(); // N(0,1)
	NormalRandomNumber( double mean, double sigma ); // N(mean,sigma)
	NormalRandomNumber( const NormalRandomNumber &that );
	NormalRandomNumber& operator= ( const NormalRandomNumber &that );
	void setGenerator( const RandomGenerator &random );
	inline double getMean() const { return _mean; }
	inline double getSigma() const { return _sigma; }
	double next();
	inline double operator++ ( int ) { return next(); }
};

#endif /* RANDOM_GENERATOR_HPP_ */
